package jtierno.organizadorMaterias.controller;

import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;

import jtierno.organizadorMaterias.model.Materia;

import org.apache.commons.collections15.Transformer;

import edu.uci.ics.jung.algorithms.layout.KKLayout;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.visualization.RenderContext;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.renderers.Renderer.VertexLabel.Position;

public class ViewController {

	private MateriasController materiasController;

	public ViewController(MateriasController materiasController) {
		this.materiasController = materiasController;
	}

	public JPanel createGrafoView(JFrame frame) {
		final VisualizationViewer<Materia, Integer> vv = crearViewer(frame);
		agregarTransformers(vv);
		return vv;
	}

	private void agregarTransformers(
			final VisualizationViewer<Materia, Integer> vv) {
		RenderContext<Materia, Integer> rendererContext = vv.getRenderContext();
		rendererContext.setVertexFillPaintTransformer(crearVertexPaintTransformer());
		rendererContext.setEdgeStrokeTransformer(crearEdgeStrokeTransformer());
		rendererContext
				.setVertexLabelTransformer(crearVertexLabelTransformer());
		rendererContext.setVertexFontTransformer(crearVertexFontTransformer());
		rendererContext.setVertexShapeTransformer(crearVertexSizeTransformer());
	}

	private VisualizationViewer<Materia, Integer> crearViewer(JFrame frame) {
		Layout<Materia, Integer> layout = new KKLayout<Materia, Integer>(
				materiasController.getGrafo());
		final VisualizationViewer<Materia, Integer> vv = new VisualizationViewer<Materia, Integer>(
				layout);
		vv.setPreferredSize(new Dimension(500, 500));
		vv.setAutoscrolls(true);
		DefaultModalGraphMouse gm = new DefaultModalGraphMouse();
		gm.setMode(ModalGraphMouse.Mode.TRANSFORMING);
		vv.setGraphMouse(gm);
        agregarJMenu(frame, gm);
		vv.getRenderer().getVertexLabelRenderer().setPosition(Position.CNTR);
		return vv;
	}

	private void agregarJMenu(JFrame frame, DefaultModalGraphMouse gm) {
		JMenuBar menuBar = new JMenuBar();
        JMenu modeMenu = gm.getModeMenu();
        modeMenu.setText("Modo del Mouse");
        modeMenu.setIcon(null); // I'm using this in a main menu
        modeMenu.setPreferredSize(new Dimension(140,20)); // Change the size so I can see the text
        menuBar.add(modeMenu);
        frame.setJMenuBar(menuBar);
	}

	private Transformer<Materia, Paint> crearVertexPaintTransformer() {
		Transformer<Materia, Paint> vertexPaint = new Transformer<Materia, Paint>() {
			public Paint transform(Materia i) {
				return i.getEstado().getColor();
			}
		};
		return vertexPaint;
	}

	private Transformer<Integer, Stroke> crearEdgeStrokeTransformer() {
		float dash[] = { 10.0f };
		final Stroke edgeStroke = new BasicStroke(1.0f, BasicStroke.CAP_BUTT,
				BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f);
		Transformer<Integer, Stroke> edgeStrokeTransformer = new Transformer<Integer, Stroke>() {
			public Stroke transform(Integer s) {
				return edgeStroke;
			}
		};
		return edgeStrokeTransformer;
	}

	private Transformer<Materia, Font> crearVertexFontTransformer() {
		Transformer<Materia, Font> vertexMateriaTransformer = new Transformer<Materia, Font>() {

			public Font transform(Materia input) {
				return new Font("Sans", Font.BOLD, 9);
			}
		};
		return vertexMateriaTransformer;
	}

	private Transformer<Materia, String> crearVertexLabelTransformer() {
		return new Transformer<Materia, String>() {

			public String transform(Materia input) {
				
				return input.getCodigo() + "-" + input.getDescripcion();
			}
		};
	}

	private Transformer<Materia, Shape> crearVertexSizeTransformer() {
		Transformer<Materia, Shape> vertexSize = new Transformer<Materia, Shape>() {
			public Shape transform(Materia i) {
				Ellipse2D circle = new Ellipse2D.Double(-15, -15, 30, 30);
				// in this case, the vertex is twice as large
				return AffineTransform.getScaleInstance(3, 3)
						.createTransformedShape(circle);
				// else return circle;
			}
		};
		return vertexSize;
	}
}
